home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / TIMER.C < prev    next >
Text File  |  1993-10-18  |  6KB  |  269 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5. #include "mbuf.h"
  6. #include "commands.h"
  7. #include "daemon.h"
  8. #include "hardware.h"
  9. #include "socket.h"
  10.  
  11. /* Head of running timer chain.
  12.  * The list of running timers is sorted in increasing order of expiration;
  13.  * i.e., the first timer to expire is always at the head of the list.
  14.  */
  15. #ifdef MDEBUG
  16. struct timer *Timers;        /* also used in alloc.c */
  17. #else
  18. static struct timer *Timers;
  19. #endif
  20.  
  21. /* Process that handles clock ticks */
  22. void
  23. timerproc(int i,void *v1,void *v2)
  24. {
  25.     struct timer *t, *p, *expired;
  26.     void (**vf)(void);
  27.     int i_state;
  28.  
  29.     for(;;){
  30.         i_state = dirps();            /* Tick is modified by an interrupt */
  31.  
  32.         while(!Tick) {
  33.             pwait(&Tick);
  34.         }
  35.         restore(i_state);
  36.  
  37.         Tick = 0;                    /* */
  38.  
  39.         if(!istate()) {
  40.             restore(1);
  41. #ifdef MDEBUG
  42.             usputs(Current->output,"\ntimer: ints were off\n\n");
  43.             usflush(Current->output);        /* make sure it gets out */
  44. #endif
  45.         }
  46.         /* Call the functions listed in config.c */
  47.         for(vf = Cfunc; *vf != NULL; vf++) {
  48.             (*vf)();
  49.         }
  50.         usflush(Current->output);        /* Flush current session output */
  51.         pwait(NULL);                    /* Let them all do their writes */
  52.  
  53.         if(Timers == NULLTIMER) {
  54.             /* No active timers, all done */
  55.             continue;
  56.         }
  57.         /* Initialize null expired timer list */
  58.         expired = NULLTIMER;
  59.  
  60.         /* Move expired timers to expired list. Note use of
  61.          * subtraction and comparison to zero rather than the
  62.          * more obvious simple comparison; this avoids
  63.          * problems when the clock count wraps around.
  64.          */
  65.         while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0) {
  66.             if(Timers->next == Timers) {
  67.                 dirps();
  68.                 iostop();
  69. #ifdef MDEBUG
  70.                 printf("\nTimer loop at %lx\n\n",(long)Timers);
  71. #else
  72.                 printf("\nTimer loop\n\n");
  73. #endif
  74.                 exit(251);
  75.             }
  76.             /* Save Timers since stop_timer will change it */
  77.             t = Timers;
  78.             stop_timer(t);
  79.  
  80.             /* Add to expired timer list */
  81.             if(expired == NULLTIMER) {
  82.                 expired = t;
  83.             } else {
  84.                 for(p = expired ; p->next != NULLTIMER ; p = p->next) ;
  85.                 p->next = t;    /* place at end of chain */
  86.             }
  87.             t->next = NULLTIMER;
  88.         }
  89.         /* Now go through the list of expired timers, removing each
  90.          * one and kicking the notify function, if there is one
  91.          * Note that the state should ne TIMER_STOP. We just stopped
  92.          * it remember? Now is someone else changed it, ignore timer.
  93.          */
  94.         while((t = expired) != NULLTIMER) {
  95.             expired = t->next;
  96.  
  97.             if(t->state == TIMER_STOP) {
  98.                 t->state = TIMER_EXPIRE;
  99.                 if(t->func) {
  100.                     (*t->func)(t->arg);
  101.                 }
  102.             }
  103.         }
  104.         pwait(NULL);    /* Let them run before handling more ticks */
  105.     }
  106. }
  107.  
  108. /* Start a timer */
  109. void
  110. start_timer(struct timer *t)
  111. {
  112.     struct timer *tnext, *tprev = NULLTIMER;
  113.  
  114.     if(t == NULLTIMER) {
  115.         return;
  116.     }
  117.     if(t->state == TIMER_RUN) {
  118.         stop_timer(t);
  119.     }
  120.     if(t->duration == 0) {
  121.         /* A duration value of 0 disables the timer */
  122.         return;
  123.     }
  124.     t->expiration = Clock + t->duration;
  125.     t->state = TIMER_RUN;
  126.  
  127.     /* Find right place on list for this guy. Once again, note use
  128.      * of subtraction and comparison with zero rather than direct
  129.      * comparison of expiration times.
  130.      */
  131.     for(tnext = Timers; tnext != NULLTIMER; tprev = tnext, tnext = tnext->next) {
  132.         if((tnext->expiration - t->expiration) >= 0) {
  133.             break;
  134.         }
  135.     }
  136.     /* At this point, tprev points to the entry that should go right
  137.      * before us, and tnext points to the entry just after us. Either or
  138.      * both may be null.
  139.      */
  140.     if(tprev == NULLTIMER) {
  141.         Timers = t;        /* Put at beginning */
  142.     } else {
  143.         tprev->next = t;
  144.     }
  145.     t->next = tnext;
  146. }
  147.  
  148. /* Stop a timer */
  149. void
  150. stop_timer(struct timer *timer)
  151. {
  152.     struct timer *t, *tlast = NULLTIMER;
  153.  
  154.     if(timer == NULLTIMER || timer->state != TIMER_RUN) {
  155.         return;
  156.     }
  157.     /* Verify that timer is really on list */
  158.     for(t = Timers; t != NULLTIMER; tlast = t, t = t->next) {
  159.         if(t == timer) {
  160.             break;
  161.         }
  162.     }
  163.     if(t == NULLTIMER) {
  164.         /* Should probably panic here */
  165.         return;
  166.     }
  167.     /* Delete from active timer list */
  168.     if(tlast != NULLTIMER) {
  169.         tlast->next = t->next;
  170.     } else {
  171.         Timers = t->next;    /* Was first on list */
  172.     }
  173.     t->state = TIMER_STOP;
  174. }
  175.  
  176. /* Return millisecs remaining on this timer */
  177. int32
  178. read_timer(struct timer *t)
  179. {
  180.     int32 remaining;
  181.  
  182.     if(t == NULLTIMER || t->state != TIMER_RUN) {
  183.         return 0;
  184.     } else {
  185.         remaining = t->expiration - Clock;
  186.     }
  187.     return (remaining <= 0) ? 0 : (remaining * MSPTICK);
  188. }
  189.  
  190. void
  191. set_timer(struct timer *t,int32 interval)
  192. {
  193.     if(t == NULLTIMER) {
  194.         return;
  195.     }
  196.     /* Round up small nonzero intervals to one tick */
  197.     t->duration = (interval != 0) ? 1 + (interval + MSPTICK - 1) / MSPTICK : 0;
  198. }
  199.  
  200. /* Delay process for specified number of millisecs
  201.  * normally returns 0, if aborted by alarm returning -1 */
  202. int
  203. pause(int32 ms)
  204. {
  205.     int val;
  206.  
  207.     if(Curproc == NULLPROC || ms == 0) {
  208.         return 0;
  209.     }
  210.     alarm(ms);
  211.  
  212.     /* The actual event doesn't matter, since we'll be alerted */
  213.     while(Curproc->alarm.state == TIMER_RUN) {
  214.         if((val = (int)pwait(Curproc)) != 0) {
  215.             break;
  216.         }
  217.     }
  218.     alarm(0L);         /* Make sure it's stopped, in case we were killed */
  219.  
  220.     return (val == EALARM) ? 0 : -1;
  221. }
  222.  
  223. static void
  224. t_alarm(void *x)
  225. {
  226.     alert((struct proc *)x,(void *)EALARM);
  227. }
  228.  
  229. /* Send signal to current process after specified number of millisecs */
  230. void
  231. alarm(int32 ms)
  232. {
  233.     if(Curproc != NULLPROC) {
  234.         set_timer(&Curproc->alarm,ms);
  235.         Curproc->alarm.func = t_alarm;
  236.         Curproc->alarm.arg = Curproc;
  237.         start_timer(&Curproc->alarm);
  238.     }
  239. }
  240.  
  241. /* Convert time count in seconds to printable days:hr:min:sec format */
  242. char *
  243. tformat(int32 t)
  244. {
  245.     static char buf[20];
  246.     char *cp = buf, minus = 0;
  247.     unsigned int days, hrs, mins, secs;
  248.  
  249.     if(t < 0) {
  250.         t = -t;
  251.         minus = 1;
  252.     }
  253.     secs = (int)(t % 60);
  254.     t /= 60;
  255.     mins = (int)(t % 60);
  256.     t /= 60;
  257.     hrs = (int)(t % 24);
  258.     t /= 24;
  259.     days = (int)(t);
  260.  
  261.     if(minus) {
  262.         *cp++ = '-';
  263.     }
  264.     sprintf(cp,"%ud:%02uh:%02um:%02us",days,hrs,mins,secs);
  265.  
  266.     return buf;
  267. }
  268.  
  269.